/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DataSource;

import Common.Constant;
import Logger.ILog;
import Logger.LogManager;
import java.util.Random;
import java.util.Vector;

/**
 *
 * @author Tuan
 */
public class DataGenerator extends PublisherImpl implements DataService{
    
    private boolean isRunning;
    
    public static final int MAX_SBP = 200;
    
    public static final int MIN_SBP = 80;
    
    public static final int MAX_DBP = 120;
    
    public static final int MIN_DBP = 50;
    
    public static final int MAX_TEMP = 45;
    
    public static final int MIN_TEMP = 30;
    
    public static final int MAX_HEART_BEAT = 120;
    
    public static final int MIN_HEART_BEAT = 50;
    
    private static final int INTERVAL = 1000;
    
    private Vector ranges = new Vector();        
    
    private static final ILog logger = LogManager.GetLogger(DataGenerator.class.getName());
    
    public DataGenerator(DataEntry entry){
        Range hypo = new Range(Constant.MIN_SBP, Constant.HYPOTENSION_MAX_SBP, Constant.MIN_DBP, Constant.HYPOTENSION_MAX_DBP, Constant.MIN_HEART_BEAT, Constant.MAX_HEART_BEAT);
        Range healthy = new Range(entry.getMinSBP(), entry.getMaxSBP(), entry.getMinDBP(), entry.getMaxDBP(), Constant.MIN_HEART_BEAT, Constant.MAX_HEART_BEAT);
        Range stage1 = new Range(Constant.HYPERTENSION_MIN_SBP_STAGE1, Constant.HYPERTENSION_MAX_SBP_STAGE1, Constant.HYPERTENSION_MIN_DBP_STAGE1, Constant.HYPERTENSION_MAX_DBP_STAGE1, entry.getMaxHeartBeat(), Constant.MAX_HEART_BEAT);
        Range stage2 = new Range(Constant.HYPERTENSION_MIN_SBP_STAGE2, Constant.HYPERTENSION_MAX_SBP_STAGE2, Constant.HYPERTENSION_MIN_DBP_STAGE2, Constant.HYPERTENSION_MAX_DBP_STAGE2, entry.getMaxHeartBeat(), Constant.MAX_HEART_BEAT);
        Range stage3 = new Range(Constant.HYPERTENSION_MIN_SBP_STAGE3, Constant.HYPERTENSION_MAX_SBP_STAGE3, Constant.HYPERTENSION_MIN_DBP_STAGE3, Constant.HYPERTENSION_MAX_DBP_STAGE3, entry.getMaxHeartBeat(), Constant.MAX_HEART_BEAT);
        ranges.addElement(hypo);
        ranges.addElement(healthy);
        ranges.addElement(stage1);
        ranges.addElement(stage2);
        ranges.addElement(stage3);
    }   
    
    public synchronized void start() {
        if(isRunning){
            return;
        }
        Thread generatorThread = new Thread(new Runnable() {

            public void run() {                
                generate();
            }
        });
        generatorThread.start();
    }
    
    private void generate(){
        isRunning = true;
        while(isRunning){
            try {
                Data data = new Data();
                data.setSystolic(generateSBP());
                data.setDiastolic(generateDBP(data.getSystolic()));
                data.setHearBeat(generateHeartBeat(data.getSystolic()));
                data.setTemperature(generateTemperature());    
                //logger.info(data.toString());
                this.notifySubscribers(data);
                Thread.sleep(INTERVAL);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
        isRunning = false;
    }

    public synchronized void stop() {
        this.isRunning = false;
        try {
            Thread.sleep(INTERVAL*2);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
    
    private int generateSBP(){
        return generateInt(MIN_SBP, MAX_SBP);
    }
    
    private int generateDBP(int sbp){
        for (int i = 0; i < ranges.size(); i++) {
            Range range = (Range)ranges.elementAt(i);
            if(range.isInRange(sbp)){
                return range.generateDbp(sbp);
            }
        }
        //there is no match!
        return generateInt(MIN_DBP, MAX_DBP);
    }
    
    private int generateHeartBeat(int sbp){
        for (int i = 0; i < ranges.size(); i++) {
            Range range = (Range)ranges.elementAt(i);
            if(range.isInRange(sbp)){
                return range.generateHb(sbp);
            }
        }                
        return generateInt(MIN_HEART_BEAT, MAX_HEART_BEAT);
    }
    
    private int generateTemperature(){
        return generateInt(MIN_TEMP, MAX_TEMP);
    }
    
    private int generateInt(int min, int max)
    {
        Random random = new Random();
        return random.nextInt(max - min + 1) + min;
    }        
}
